//
//	MiscDistributor.m -- An object which will pass a message on to any of
//			the objects connected to it, even across .nib file boundaries.
//
//		Written by Don Yacktman.  Copyright 1994 by Don Yacktman.
//				Version 1.0  All rights reserved.
//
//		This notice may not be removed from this source code.
//
//	This object is included in the MiscKit by permission from the author
//	and its use is governed by the MiscKit license, found in the file
//	"LICENSE.rtf" in the MiscKit distribution.  Please refer to that file
//	for a list of all applicable permissions and restrictions.
//	

#import <appkit/appkit.h>
#import "MiscDistributor.h"
#define INSUBPROJ
#import "../_MiscDistributorConnection.h"
#import "../MiscDistributorPrivate.h"

static id distributors = nil; // to be a HashTable

#define CURRENT_VERSION 1
#define STARTINGCAPACITY 512	// you may need this a lot larger.

@implementation MiscDistributor(private)

- _connectionList { return connections; }
- _makeConnections
{
	int i;
	for (i=0; i<[connections count]; i++) {
		id aConnection = [connections objectAt:i];
		[self connectToDistributorNamed:[aConnection connectionName]
				direction:[aConnection direction]];
	}
	return self;
}

@end

@implementation MiscDistributor

+ initialize
{
	// set up class version number and set up the waiting list and
	// distributors dictionary
	if (self == [MiscDistributor class]) {
		[MiscDistributor setVersion:CURRENT_VERSION];
		if (!distributors) distributors = [[HashTable alloc]
				initKeyDesc:"%" valueDesc:"@" capacity:STARTINGCAPACITY];
	}
	return self;
}

+ findDistributorNamed:(const char *)aString
{
	// extract object from the hash table, creating if needed.
	id theDistributor; NXAtom key;
	if (!aString) return nil;
	if (!strlen(aString)) return nil;
	if (!distributors) distributors = [[HashTable alloc]
			initKeyDesc:"%" valueDesc:"@" capacity:STARTINGCAPACITY];
	key = NXUniqueString(aString);
	// OK, have a name.  Is it in the table?
	theDistributor = [distributors valueForKey:key];
	if (!theDistributor) {
		theDistributor = [[MiscTee alloc] init];
		[distributors insertKey:key value:theDistributor];
	}
	return theDistributor;
}

- init
{
	[super init];
	connections = [[List alloc] init];
	return self;
}

- connectToDistributorNamed:(const char *)aString
		direction:(MiscDCDirection)direction
{	// sets up an actual connection
	id theTee = [[self class] findDistributorNamed:aString];
	BOOL doIn = NO; BOOL doOut = NO;

	switch (direction) {
		case MiscIn		: { doIn = YES;					break; }
		case MiscOut	: {				doOut = YES;	break; }
		case MiscInout	: { doIn = YES;	doOut = YES;	break; }
		default			: {								break; }
	}
	if (doIn) [theTee addConnection:self with:@selector(ping:)];
	if (doOut) [self addConnection:theTee with:@selector(ping:)];
	return self;
}

- awakeFromNib
{
	[self _makeConnections];
	return self;
}

- read:(NXTypedStream *)stream
{
	int version;

	[super read:stream];
	version = NXTypedStreamClassVersion(stream,"MiscDistributor");
	if (version == CURRENT_VERSION) {
		connections = NXReadObject(stream);
	}
	if (!connections) connections = [[List alloc] init];
	return self;
}

- write:(NXTypedStream *)stream
{
	[super write:stream];
	NXWriteObject(stream, connections);
	return self;
}

@end
